package cn.good.yan.config.demo3;

import com.alibaba.fastjson2.JSON;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

import java.util.HashMap;

/**
 * 三
 * 1. Spring Security - 自定义配置
 * 【授权】
 * 演示：
 * 1. 用户授权， hasAuthority，配置哪些请求，有哪些权限
 * 2。基于方法的授权，开启 @EnableMethodSecurity 注解
 *
 * @author shengren.yan
 * @create 2024-07-16
 */
@EnableMethodSecurity
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

    // 演示：授权 - 开启授权保护
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                // 1.用户权限资源的配置
//                .authorizeRequests(authorize -> {
//                    authorize
//                            // 具有 LIST权限 的用户可以访问 /user/list
//                            .requestMatchers("/user/list").hasAuthority("LIST")
//                            // 具有 ADD权限 的用户可以访问 /user/add
//                            .requestMatchers("/user/save").hasAuthority("ADD")
//                            .anyRequest()      // 对所有请求开启授权保护
//                            .authenticated();  // 已认证的请求会自动授权
//                })

                // 2.用户角色资源配置
//                .authorizeRequests(authorize -> {
//                    authorize
//                            // 具有管理员角色(ADMIN)的用户可以访问/user/**
//                            .requestMatchers("/user/**").hasRole("ADMIN")
//                            .anyRequest()      // 对所有请求开启授权保护
//                            .authenticated();  // 已认证的请求会自动授权
//                })

                // 3.基于方法的授权
                .authorizeRequests(authorize -> {
                    authorize
                            .anyRequest()      // 对所有请求开启授权保护
                            .authenticated();  // 已认证的请求会自动授权
                })

                .formLogin(form -> {
                    form
                            .loginPage("/login").permitAll()   // 登录页面无需授权即可访问
                            .usernameParameter("username")     // 自定义表单用户名参数，默认是username
                            .passwordParameter("password")     // 自定义表单密码参数，默认是password
                            .failureUrl("/login?error")       //登录失败的返回地址
                            .successHandler(new MyAuthenticationSuccessHandler()) //认证成功时的处理
                            .failureHandler(new MyAuthenticationFailureHandler()) //认证失败时的处理
                    ;
                });
        http.logout(logout -> {
            logout.logoutSuccessHandler(new MyLogoutSuccessHandler()); // 注销成功时的处理
        });
        http.exceptionHandling(exception -> {
            exception.authenticationEntryPoint(new MyAuthenticationEntryPoint()); // 请求未认证的接口
            // 未授权的返回json结构，该部分使用 匿名内部类方式，没有进行创建类
            exception.accessDeniedHandler((request, response, e) -> { // 请求未授权的接口
                // 创建结果对象
                HashMap<String, Object> result = new HashMap();
                result.put("code", -1);
                result.put("message", "没有权限");
                //转换成json字符串
                String json = JSON.toJSONString(result);
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().println(json);
            });
        });
        // 会话管理 - 处理
        http.sessionManagement(session -> {
            session
                    .maximumSessions(1)
                    .expiredSessionStrategy(new MySessionInformationExpiredStrategy());
        });
        // 跨域处理
        http.cors(Customizer.withDefaults());
        // 暂时关闭csrf攻击
        http.csrf(csrf -> csrf.disable());
        return http.build();
    }

}
